package com.shenhangye.pushlive.opengl

import android.content.Context
import android.graphics.BitmapFactory
import android.opengl.GLES11Ext
import android.opengl.GLES30
import android.opengl.GLUtils
import android.util.Log
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.IntBuffer

object openglutil {


    /**
     * Checks to see if a GLES error has been raised.
     */
    fun checkGlError(op: String) {
        val error = GLES30.glGetError()
        if (error != GLES30.GL_NO_ERROR) {
            val msg = op + ": glError 0x" + Integer.toHexString(error)
            Log.e(TAG, msg)
            throw RuntimeException(msg)
        }
    }
    fun createTexture(oes:IntArray,context: Context){

        GLES30.glGenTextures(oes.size,oes,0)

        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,oes[0])


        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
        var bitmape=BitmapFactory.decodeResource(context.resources,com.shenhangye.pushlive.R.drawable.img)
        GLUtils.texImage2D(GLES30.GL_TEXTURE_2D,0,bitmape,0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,0)
    }
    fun createOes(oes:IntArray){

        GLES30.glGenTextures(oes.size,oes,0)

        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,oes[0])


        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,0)
    }
    fun createIntBuffer(array: IntArray): IntBuffer {
        val buffer = ByteBuffer
            // 分配顶点坐标分量个数 * Float占的Byte位数
            .allocateDirect(array.size * 4)
            // 按照本地字节序排序
            .order(ByteOrder.nativeOrder())
            // Byte类型转Float类型
            .asIntBuffer()

        // 将Dalvik的内存数据复制到Native内存中
        buffer.put(array)
        buffer.position(0)
        return buffer
    }
    fun createFloatBuffer(array:FloatArray): FloatBuffer {
        val buffer = ByteBuffer
            // 分配顶点坐标分量个数 * Float占的Byte位数
            .allocateDirect(array.size * 4)
            // 按照本地字节序排序
            .order(ByteOrder.nativeOrder())
            // Byte类型转Float类型
            .asFloatBuffer()

        // 将Dalvik的内存数据复制到Native内存中
        buffer.put(array)
        buffer.position(0)
        return buffer
    }
    fun readRawTextFile(context: Context, rawId: Int):String{
        val `is` = context.resources.openRawResource(rawId)
        val br = BufferedReader(InputStreamReader(`is`))
        var line: String?
        val sb = StringBuilder()
        try {
            while ((br.readLine().also { line = it }) != null) {
                sb.append(line)
                sb.append("\n")
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        try {
            br.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return sb.toString()
    }
    private const val TAG = "openglutil"

    private fun compileShader(type: Int, shaderCode: String): Int {

        //创建一个着色器
        val shaderId = GLES30.glCreateShader(type)
        if (shaderId != 0) {
            //加载到着色器
            GLES30.glShaderSource(shaderId, shaderCode)
            //编译着色器
            GLES30.glCompileShader(shaderId)
            //检测状态
            val compileStatus = IntArray(1)
            GLES30.glGetShaderiv(shaderId, GLES30.GL_COMPILE_STATUS, compileStatus, 0)
            if (compileStatus[0] == 0) {
                val logInfo = GLES30.glGetShaderInfoLog(shaderId)
                System.err.println(logInfo)
                Log.e(TAG,type.toString()+"---");
                Log.e(TAG,logInfo);
                //创建失败
                GLES30.glDeleteShader(shaderId)
                return 0
            }
            return shaderId
        } else {
            //创建失败
            return 0
        }
    }


    fun createProgram(context:Context,verId:Int,frgId:Int):Int{
        var fracre= compileShader(GLES30.GL_FRAGMENT_SHADER, readRawTextFile(context,frgId));
        var vercre= compileShader(GLES30.GL_VERTEX_SHADER, readRawTextFile(context,verId));

        val program=GLES30.glCreateProgram();

        GLES30.glAttachShader(program,vercre);
        GLES30.glAttachShader(program,fracre);

        GLES30.glLinkProgram(program)

        GLES30.glDeleteShader(vercre)
        GLES30.glDeleteShader(fracre)
        return program;
    }



}